package com.tange.ai.core.demo.player;

import android.Manifest;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;

import com.tange.ai.core.demo.R;
import com.tange.ai.core.demo.databinding.ActivityPlayerBinding;
import com.tange.core.data.structure.Device;
import com.tange.module.camera.reconnection.LimitTimeReconnectionStrategy;
import com.tange.module.camera.reconnection.ReconnectionStrategy;
import com.tange.module.media.play.combine.MediaPlayCombination;
import com.tange.module.media.play.decoration.MediaCoverDisplay;
import com.tange.module.media.play.render.MediaPlayRenderListener;
import com.tange.module.media.play.talkback.DeviceTalkback;
import com.tange.module.media.source.impl.CameraMediaSource;
import com.tg.app.camera.AVIOCTRLDEFs;
import com.tg.app.camera.Camera;
import com.tg.appcommon.android.Packet;
import com.tg.data.media.OnICameraListener;

import java.io.File;
import java.util.Calendar;

public class PlayerViewDelegate extends BaseViewDelegate {

    // 将一个小时转换为毫秒
    private static final int HOUR_MS = 60 * 60 * 1000;

    // 查询 设备配置 的指令：(具体参考设备端的文档)
    public static final int IOTYPE_USER_IPCAM_DEVINFO_REQ = 0x0330;
    public static final int IOTYPE_USER_IPCAM_DEVINFO_RESP = 0x0331;

    // 设置画面旋转:
    public static final int IOTYPE_USER_IPCAM_SET_VIDEOMODE_REQ = 0x0370;
    public static final int AVIOCTRL_VIDEOMODE_NORMAL = 0x00;
    public static final int AVIOCTRL_VIDEOMODE_FLIP_MIRROR = 0x03;

    // 手机相册文件夹路径
    private String sdDirPath = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_DCIM;

    /** 重试策略 */
    private ReconnectionStrategy reconnectionStrategy;

    /** 媒体数据源-来自摄像头 */
    private CameraMediaSource cameraMediaSource;

    /** 通用播放器 */
    private MediaPlayCombination playCombination;

    /** 封面展示 */
    private MediaCoverDisplay mediaCoverDisplay;

    /** 摄像头状态与命令回调 */
    private OnICameraListener onICameraListener;

    /** 设备对讲模块 */
    private DeviceTalkback deviceTalkback;

    private boolean isAudioOn = true;
    private boolean isMicrophoneOn = false;
    private boolean isVideoRecording = false;
    private boolean isLandscape = false;
    private boolean isSdCardStatusRequest = false;
    private boolean isSdCardPlaying = false;
    private boolean isVideoReversed = false;

    public PlayerViewDelegate(Activity activity, ActivityPlayerBinding binding, Device device) {
        super(activity, binding, device);
    }

    @Override
    public void onCreate() {

        // 初始化媒体数据源
        initDataSource();

        // 初始化播放器
        initPlayer();

        // 加载封面图
        loadCover();

        // 按钮：返回
        binding.back.setOnClickListener(v -> onBackClick());

        // 按钮：重试连接
        binding.connect.setOnClickListener(v -> startConnect());

        // 按钮：音频开关
        binding.volume.setOnClickListener(v -> switchAudioTransport());

        // 按钮：截屏
        binding.screenShot.setOnClickListener(v -> takeScreenShot());

        // 按钮：录屏
        binding.screenRecord.setOnClickListener(v -> takeScreenRecord());

        // 按钮：对讲开关
        binding.talkback.setOnClickListener(v -> talkback());

        // 按钮：屏幕旋转
        binding.fullScreen.setOnClickListener(v -> switchFullScreen());

        // 按钮：播放摄像头SD卡中的录像
        binding.sdCardPlayBack.setOnClickListener(v -> playBackFromSdCard());

        // 按钮：上下翻转画面（通过命令）
        binding.videoReverse.setOnClickListener(v -> reverseVideo());


        // 设置接收视频
        cameraMediaSource.cameraLiveControl().enableVideoReceive();
        // 设置接收音频
        cameraMediaSource.cameraLiveControl().enableAudioReceive();
        // 开始连接摄像头，获取数据流
        startConnect();
    }

    private void reverseVideo() {
        if (!cameraMediaSource.cameraInteraction().connected()) {
            Toast.makeText(activity, "设备未连接！", Toast.LENGTH_SHORT).show();
            return;
        }
        // 设置 视频画面 翻转 180度，具体指令和参数，请参考 设备侧文档！
        if (isVideoReversed) {
            cameraMediaSource.cameraInteraction().sendCommand(IOTYPE_USER_IPCAM_SET_VIDEOMODE_REQ, AVIOCTRLDEFs.SMsgAVIoctrlSetVideoModeReq.parseContent(0, AVIOCTRL_VIDEOMODE_NORMAL, (byte)0));
        } else {
            cameraMediaSource.cameraInteraction().sendCommand(IOTYPE_USER_IPCAM_SET_VIDEOMODE_REQ, AVIOCTRLDEFs.SMsgAVIoctrlSetVideoModeReq.parseContent(0, AVIOCTRL_VIDEOMODE_FLIP_MIRROR, (byte)0));
        }
        isVideoReversed = !isVideoReversed;

        Toast.makeText(activity, "已向设备发送 画面翻转 指令", Toast.LENGTH_SHORT).show();
    }

    private void playBackFromSdCard() {
        if (!cameraMediaSource.cameraInteraction().connected()) {
            Toast.makeText(activity, "设备未连接！", Toast.LENGTH_SHORT).show();
            return;
        }
        if (isSdCardPlaying) {
            cameraMediaSource.setSourceMode(CameraMediaSource.SOURCE_MODE_LIVE);
            Toast.makeText(activity, "开始播放实时录像...", Toast.LENGTH_SHORT).show();
            binding.sdCardPlayBack.setImageResource(R.drawable.ic_baseline_sd_card_24);
        } else {
            cameraMediaSource.setSourceMode(CameraMediaSource.SOURCE_MODE_PLAYBACK);
            cameraMediaSource.cameraPlaybackControl().start(System.currentTimeMillis() - 2 * HOUR_MS);
            Toast.makeText(activity, "进入SD卡回看模式：从 2小时前 开始播放...", Toast.LENGTH_SHORT).show();
            binding.sdCardPlayBack.setImageResource(R.drawable.ic_baseline_sd_card_on_24);
        }
        isSdCardPlaying = !isSdCardPlaying;
    }

    private void onBackClick() {
        if (isLandscape) {
            switchFullScreen();
        } else {
            activity.finish();
        }
    }

    private void switchFullScreen() {
        if (isLandscape) {
            binding.bottomLayout.setVisibility(View.VISIBLE);
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            isLandscape = false;
        } else {
            binding.bottomLayout.setVisibility(View.GONE);
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            isLandscape = true;
        }
    }

    private void talkback() {
        if (!cameraMediaSource.cameraInteraction().connected()) {
            Toast.makeText(activity, "设备未连接！", Toast.LENGTH_SHORT).show();
            return;
        }

        final boolean isPermissionGranted = ActivityCompat.checkSelfPermission(activity,
                Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED;

        if (!isPermissionGranted) {

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                activity.requestPermissions(new String[] {Manifest.permission.RECORD_AUDIO}, 100);
            }

            Toast.makeText(activity, "需要录音权限！", Toast.LENGTH_SHORT).show();
            return;
        }

        if (deviceTalkback == null) {
            deviceTalkback = DeviceTalkback.create(true, cameraMediaSource.cameraInteraction().camera());
        }

        if (isMicrophoneOn) {
            binding.talkback.setImageResource(R.drawable.ic_baseline_mic_off_24);
            Toast.makeText(activity, "对讲停止", Toast.LENGTH_SHORT).show();
            deviceTalkback.stopTalk();
            isMicrophoneOn = false;
        } else {
            binding.talkback.setImageResource(R.drawable.ic_baseline_mic_24);
            Toast.makeText(activity, "对讲开始", Toast.LENGTH_SHORT).show();
            deviceTalkback.startTalk();
            isMicrophoneOn = true;
        }
    }

    private void takeScreenRecord() {

        final boolean isPermissionGranted = ActivityCompat.checkSelfPermission(activity,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;

        if (!isPermissionGranted) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                activity.requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
            }
            Toast.makeText(activity, "需要存储权限！", Toast.LENGTH_SHORT).show();
            return;
        }

        if (isVideoRecording) {
            boolean ret = playCombination.mainScreenRecord().finish();
            if (ret) {
                File targetFile = new File(sdDirPath, System.currentTimeMillis() + ".mp4");
                boolean exportRet = playCombination.mainScreenRecord().export(targetFile.getAbsolutePath());
                if (exportRet) {
                    Toast.makeText(activity, "录屏已保存到相册", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(activity, "录屏保存失败！", Toast.LENGTH_SHORT).show();
                }
            } else {
                Toast.makeText(activity, "录屏保存失败！", Toast.LENGTH_SHORT).show();
            }
            isVideoRecording = false;
            binding.screenRecord.setImageResource(R.drawable.ic_baseline_videocam_24);
        } else {
            playCombination.mainScreenRecord().start();
            isVideoRecording = true;
            Toast.makeText(activity, "开始录屏，再次点击结束录屏", Toast.LENGTH_SHORT).show();
            binding.screenRecord.setImageResource(R.drawable.ic_baseline_videocam_off_24);
        }
    }

    private void takeScreenShot() {
        final boolean isPermissionGranted = ActivityCompat.checkSelfPermission(activity,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;

        if (!isPermissionGranted) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                activity.requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
            }
            Toast.makeText(activity, "需要存储权限！", Toast.LENGTH_LONG).show();
            return;
        }


        File targetFile = new File(sdDirPath, System.currentTimeMillis() + ".jpg");
        boolean ret = playCombination.exportMainScreenshot(targetFile.getAbsolutePath());
        if (ret) {
            Toast.makeText(activity, "截图已保存到相册", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(activity, "截图保存失败！", Toast.LENGTH_LONG).show();
        }
    }

    private void switchAudioTransport() {
        if (isAudioOn) {
            binding.volume.setImageResource(R.drawable.ic_baseline_volume_off_24);
            isAudioOn = false;
            cameraMediaSource.cameraLiveControl().disableAudioReceive();
            Toast.makeText(activity, "设备声音已关", Toast.LENGTH_SHORT).show();

        } else {
            binding.volume.setImageResource(R.drawable.ic_baseline_volume_on_24);
            isAudioOn = true;
            cameraMediaSource.cameraLiveControl().enableAudioReceive();
            Toast.makeText(activity, "设备声音已开", Toast.LENGTH_SHORT).show();
        }
    }

    private void startConnect() {
        cameraMediaSource.cameraInteraction().connect();

        binding.playerContainer.post(() -> binding.connect.setVisibility(View.GONE));
        binding.playerContainer.post(() -> binding.loading.setVisibility(View.VISIBLE));
    }

    private void initDataSource() {
        cameraMediaSource = new CameraMediaSource(device);

        reconnectionStrategy = new LimitTimeReconnectionStrategy(10 * 1000);
        reconnectionStrategy.setCallback(new ReconnectionStrategy.Callback() {
            @Override
            public void onRetry() {
                binding.playerContainer.post(() -> binding.loading.setVisibility(View.VISIBLE));
                binding.playerContainer.post(() -> binding.tips.setText("重试中"));
            }

            @Override
            public void onNoMoreRetry() {
                binding.playerContainer.post(() -> binding.connect.setVisibility(View.VISIBLE));
                binding.playerContainer.post(() -> binding.connect.setText("连接失败，再试一次"));
            }
        });
        cameraMediaSource.cameraInteraction().setReconnectionStrategy(reconnectionStrategy);

        cameraMediaSource.setSourceMode(CameraMediaSource.SOURCE_MODE_LIVE);
        cameraMediaSource.cameraLiveControl().setStreamQuality(AVIOCTRLDEFs.AVIOCTRL_QUALITY_MIN);
        // 音视频传输场景下，务必设置此项
        cameraMediaSource.cameraInteraction().setTransportMedia(true);

        onICameraListener = new OnICameraListener() {
            @Override
            public void receiveUpdateConnectStates(int status) {
                if (status == Camera.CONNECTION_STATE_CONNECTED) {
                    binding.playerContainer.post(() -> binding.loading.setVisibility(View.GONE));
                    binding.playerContainer.post(() -> binding.connect.setVisibility(View.GONE));

                    // 查询设备信息，获取SD卡容量：
                    if (!isSdCardStatusRequest) {
                        cameraMediaSource.cameraInteraction().sendCommand(IOTYPE_USER_IPCAM_DEVINFO_REQ, new byte[] {});
                    }
                }
            }

            @Override
            public void receiveIOCtrlData(int cmd, byte[] data) {

                if (cmd == IOTYPE_USER_IPCAM_DEVINFO_RESP) {
                    // 第40位，存储了SD卡的容量，具体参考设备端文档
                    final int totalSize = Packet.byteArrayToInt_Little(data, 40);
                    isSdCardStatusRequest = true;
                    binding.sdCardPlayBack.post(() -> {
                        if (totalSize > 0) {
                            binding.sdCardPlayBack.setImageResource(R.drawable.ic_baseline_sd_card_24);
                            binding.sdCardPlayBack.setEnabled(true);
                        } else {
                            binding.sdCardPlayBack.setImageResource(R.drawable.ic_baseline_sd_card_disable_24);
                            binding.sdCardPlayBack.setEnabled(false);
                        }
                    });
                }
            }
        };

        cameraMediaSource.cameraInteraction().addOnICameraListeners(onICameraListener);
    }

    private void initPlayer() {
        playCombination = new MediaPlayCombination(activity, device, cameraMediaSource);
        // 若本页面开启双向对讲，需要设置此处为true，
        playCombination.setAudioPlayInCommunicationMode(false);
        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
        playCombination.attachMainVideoToView(binding.playerContainer, lp);
        playCombination.setMediaPlayRenderListener(new MediaPlayRenderListener() {

            @Override
            public void onVideoFirstFrameRendered() {
                binding.playerContainer.post(() -> binding.cover.setVisibility(View.GONE));
                binding.playerContainer.post(() -> binding.connect.setVisibility(View.GONE));
                binding.playerContainer.post(() -> binding.loading.setVisibility(View.GONE));
            }

            @Override
            public void onVideoSizeChanged(int width, int height, boolean reverse) {

            }

            @Override
            public void onVideoPlayStateChanged(boolean isStart) {

            }
        });
        playCombination.create();
    }

    private void loadCover() {
        mediaCoverDisplay = new MediaCoverDisplay(activity, binding.cover, device, device.getCover());
        mediaCoverDisplay.setCallback(new MediaCoverDisplay.Callback() {
            @Override
            public void onSuccess(Bitmap bitmap, boolean b) {

            }

            @Override
            public void onFailed() {

            }
        });
        mediaCoverDisplay.load();
    }

    @Override
    public void onResume() {
        playCombination.resume();
    }

    @Override
    public void onPause() {
        playCombination.pause();
    }

    @Override
    public void onDestroy() {
        cameraMediaSource.cameraInteraction().removeOnICameraListeners(onICameraListener);
        playCombination.destroy();
    }
}
